home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / v9n09.arc / WHEREIS.C < prev    next >
Text File  |  1990-04-09  |  13KB  |  301 lines

  1. /*
  2.     WHEREIS.C for OS/2 version 1.2
  3.  
  4.     A file finder utility that searches the current or specified drive, 
  5.     starting with the root directory (\), for the specified pathname.  
  6.     Wildcard characters can be included.  Long filenames are supported.  
  7.     If an extended attribute name and value is also supplied, that 
  8.     information is also used as a match criterion.  Blanks can be 
  9.     embedded in the EA value by quoting.  The current version of
  10.     the program only knows how to handle length-preceded ASCII EAs.
  11.  
  12.     This program does not require Microsoft or IBM Programmer's Toolkit
  13.     header files, but must be linked using LINK.EXE and DOSCALLS.LIB 
  14.     from retail OS/2 version 1.2.
  15.  
  16.     Compile:    cl -c /Zi whereis.c
  17.                 link /CO whereis,whereis,,doscalls,whereis.def;
  18.  
  19.     Usage:      whereis pathname [EAname=EAvalue]
  20.  
  21.     Examples:   whereis *.ico                     (match filename only)
  22.                 whereis * .TYPE=Icon              (match EA only)
  23.                 whereis *.ico .TYPE=Icon          (match both)
  24.                 whereis *.txt ".TYPE=Plain Text"  (match both)
  25.  
  26.     Copyright (C) 1989 Ziff-Davis Communications
  27.     PC Magazine * Ray Duncan
  28. */
  29.  
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <memory.h>
  33. #include <malloc.h>
  34.  
  35. #define API unsigned extern far pascal  // OS/2 API function prototypes 
  36. API DosChDir(char far *, unsigned long);
  37. API DosFindClose(unsigned);
  38. API DosFindFirst2(char far *, unsigned far *, unsigned, void far *,
  39.                   unsigned, int far *, int, unsigned long);
  40. API DosFindNext(unsigned, void far *, int, int far *);
  41. API DosQPathInfo(void far *, unsigned, char far *, int, unsigned long);
  42. API DosSelectDisk(int);
  43. API DosWrite(unsigned, void far *, unsigned, unsigned far *);
  44.  
  45. void showfile(char far *);              // local function prototypes
  46. void schdir(char *);
  47. void schfile(void);
  48.  
  49. #define NORM      0x00                  // old file attribute bits 
  50. #define RD_ONLY   0x01
  51. #define HIDDEN    0x02
  52. #define SYSTEM    0x04
  53. #define DIR       0x10
  54. #define ARCHIVE   0x20
  55.                                         // EA predefined value types
  56. #define EAT_BINARY      0x0fffe         // Length-preceeded binary
  57. #define EAT_ASCII       0x0fffd         // Length-preceeded ASCII
  58. #define EAT_BITMAP      0x0fffb         // Length-preceeded bitmap
  59. #define EAT_METAFILE    0x0fffa         // Metafile
  60. #define EAT_ICON        0x0fff9         // Length-preceeded icon
  61. #define EAT_EA          0x0ffee         // ASCIIZ name of associated EA
  62. #define EAT_MVMT        0x0ffdf         // Multi-value multi-type
  63. #define EAT_MVST        0x0ffde         // Multi-value single-type
  64. #define EAT_ASN1        0x0ffdd         // ASN.1 field
  65.  
  66.                                         // arbitrary buffer sizes
  67. #define SCHBUF_SIZE     4096            // size of search buffer
  68. #define TEAVAL_SIZE     260             // max size of EA target value
  69. #define GEALIST_SIZE    260             // max size of target GEAList
  70. #define MAXPATHNAME     260             // max length of pathname
  71. #define MAXFILENAME     255             // max length of filename
  72.  
  73. struct _EA {                            // extended attribute header 
  74.         unsigned char flags;            // critical flag etc.
  75.         unsigned char nsize;            // length of EA name (without null)
  76.         unsigned vsize;                 // total size of EA value
  77.         char name[1]; } ;               // EA name and value begin here
  78.  
  79. struct _EAval {                         // extended attribute value 
  80.         unsigned type;                  // EA value type
  81.         unsigned size;                  // length of EA variable data
  82.         char data[1]; } ;               // actual data begins here
  83.  
  84. struct _FEAList {                       // receives extended attributes
  85.         unsigned long size;             // total size of structure
  86.         char data[1]; } ;               // extended attributes begin here
  87.  
  88. struct _GEA {                           // extended attribute target name
  89.         unsigned char size;             // length of name
  90.         char name[1]; } ;               // actual name begins here
  91.  
  92. struct _GEAList {                       // holds names of EAs to get
  93.         unsigned long size;             // total size of structure
  94.         struct _GEA GEA; } ;            // name length and name text
  95.  
  96. struct _EAOP {                          // used by all EA functions
  97.         void far *pGEAList;             // pointer to GEAList structure         
  98.         void far *pFEAList;             // pointer to FEAList structure
  99.         unsigned long oError; } ;       // offset of error, if any
  100.  
  101. struct _info1 {                         // result buffer format for
  102.                     unsigned cdate;     // DosFindFirst2 info level 1
  103.                     unsigned ctime;
  104.                     unsigned adate;
  105.                     unsigned atime;
  106.                     unsigned wdate;
  107.                     unsigned wtime; 
  108.                     long fsize;
  109.                     long falloc;
  110.                     unsigned fattr;
  111.                     char fcount;
  112.                     char fname[MAXFILENAME]; 
  113.              } ;
  114.  
  115. struct _info3 {                         // result buffer format for
  116.                     struct _EAOP EAOP;  // DosFindFirst2 info level 3
  117.                     unsigned cdate;
  118.                     unsigned ctime;
  119.                     unsigned adate;
  120.                     unsigned atime;
  121.                     unsigned wdate;
  122.                     unsigned wtime; 
  123.                     long fsize;
  124.                     long falloc;
  125.                     unsigned fattr;
  126.                     long easize;
  127.                     struct _EA EA;
  128.              } ; 
  129.  
  130. union _sbuf {
  131.                     struct _info1 info1;
  132.                     struct _info3 info3;
  133.             } ;
  134.  
  135. struct _GEAList *GEAList = NULL;        // pointer to EA name buffer
  136. union  _sbuf    *sbuf = NULL;           // pointer to search result buffer
  137. struct _EAval   *tEAval = NULL;         // pointer to EA value buffer
  138. char            *tfname = NULL;         // pointer to filename buffer
  139. int count = 0;                          // total files matched 
  140.  
  141.  
  142. main(int argc, char *argv[])
  143. {
  144.     if((argc < 2) || (argc > 3))        // check command line
  145.     {
  146.         printf("\nUsage:     whereis filename [EAname=EAvalue]\n");
  147.         printf("\n           EA name is case-sensitive, EA value is not.");
  148.         printf("\n           Use quotes to embed blanks in EA value.\n");
  149.         printf("\nExamples:  whereis *.ico");
  150.         printf("\n           whereis * .TYPE=Icon");
  151.         printf("\n           whereis *.ico .TYPE=Icon");
  152.         printf("\n           whereis *.txt \".TYPE=Plain Text\"\n");
  153.         exit(1);
  154.     }
  155.  
  156.     sbuf    = malloc(SCHBUF_SIZE);      // allocate buffers; note that
  157.     GEAList = malloc(GEALIST_SIZE);     // these sizes are arbitrary
  158.     tEAval  = malloc(TEAVAL_SIZE);
  159.     tfname  = malloc(MAXFILENAME);
  160.  
  161.     if((sbuf==NULL) || (GEAList==NULL) || (tEAval==NULL) || (tfname==NULL))
  162.     {
  163.         printf("\nwhereis: heap allocation error\n");
  164.         exit(1);
  165.     }
  166.  
  167.     if(((strlen(argv[1])) >= 2) && ((argv[1])[1] == ':'))
  168.     {
  169.         if(DosSelectDisk(((argv[1]) [0] | 0x20) - ('a'-1)))
  170.         {
  171.             printf("\nwhereis: bad drive\n");
  172.             exit(1);
  173.         }
  174.  
  175.         argv[1] += 2;                   // advance past drive 
  176.     }
  177.  
  178.     strncpy(tfname, argv[1], MAXFILENAME);  // save target filename
  179.  
  180.     if(argc == 3)                       // parse EA search target
  181.     {                                   // into name and value strings
  182.         strcpy(GEAList->GEA.name, strtok(argv[2], " =\x0a"));
  183.         GEAList->GEA.size = strlen(GEAList->GEA.name);
  184.         GEAList->size = GEAList->GEA.size + 6;
  185.  
  186.         strcpy(tEAval->data, strtok(NULL, "\x0a"));
  187.         tEAval->size  = strlen(tEAval->data);
  188.     }
  189.     else                                // if no EA search target
  190.     {                                   // supplied, force length
  191.         GEAList->GEA.size = 0;          // of name and value to 0
  192.         tEAval->size = 0;   
  193.         GEAList->size = sizeof(GEAList->size);
  194.     }
  195.  
  196.     schdir("\\");                       // start search with root 
  197.  
  198.     if(count == 0)                      // advise if no matches
  199.         printf("\nwhereis: no files\n");
  200. }
  201.  
  202. /*
  203.     SCHDIR: search specified directory for matching files and
  204.     any other directories which can be searched recursively.
  205. */
  206. void schdir(char *dirname)
  207. {
  208.     unsigned shandle = -1;              // search handle 
  209.     int scount = 1;                     // max search matches 
  210.  
  211.     DosChDir(dirname, 0L);              // select new directory 
  212.  
  213.     schfile();                          // find and list files 
  214.  
  215.                                         // search for directories 
  216.     if(!DosFindFirst2("*.*",            // match any name
  217.                       &shandle,         // receives search handle
  218.                       NORM|DIR,         // match normal files & dirs
  219.                       sbuf,             // buffer receives match info
  220.                       SCHBUF_SIZE,      // size of search buffer
  221.                       &scount,          // receives match count
  222.                       1,                // info level 1 = no EAs
  223.                       0L))              // reserved 
  224.     {
  225.         do                              // recurse to search directories 
  226.         {                               // other than . and .. aliases 
  227.             if((sbuf->info1.fattr & DIR) && (sbuf->info1.fname[0] != '.'))
  228.             {
  229.                 schdir(sbuf->info1.fname);      
  230.                 DosChDir("..", 0L);     // restore previous directory                          
  231.             }
  232.                                         // look for more directories 
  233.         } while(DosFindNext(shandle, sbuf, SCHBUF_SIZE, &scount) == 0);
  234.     }
  235.  
  236.     DosFindClose(shandle);              // close search handle 
  237. }
  238.  
  239. /*
  240.     SCHFILE: search current directory for files matching supplied
  241.     filename, also matching extended attribute name and value if any.
  242. */
  243. void schfile(void)
  244. {
  245.     struct _EAval *pEAval;              // pointer to EA value in sbuf
  246.     char far *pfname;                   // pointer to filename
  247.  
  248.     unsigned shandle = -1;              // search handle 
  249.     int scount = 1;                     // max search matches 
  250.  
  251.     sbuf->info3.EAOP.oError = 0L;       // initialize EAOP pointers
  252.     sbuf->info3.EAOP.pGEAList = GEAList;        
  253.     sbuf->info3.EAOP.pFEAList = NULL;
  254.  
  255.     if(!DosFindFirst2(tfname,           // target filename for search
  256.                       &shandle,         // receives search handle
  257.                       NORM,             // match normal files only
  258.                       sbuf,             // buffer receives match info
  259.                       SCHBUF_SIZE,      // size of search buffer
  260.                       &scount,          // receives match count
  261.                       3,                // info level 3 = get EAs too
  262.                       0L))              // reserved 
  263.     {
  264.         do
  265.         {   
  266.             pfname  = (char far *)      // calc address of filename
  267.                 &sbuf->info3.easize + sbuf->info3.easize + 1;
  268.  
  269.             if(tEAval->size)            // if EA entered, does it match?
  270.             {
  271.                 (char *) pEAval =       // calc address of EA value
  272.                     sbuf->info3.EA.name + sbuf->info3.EA.nsize + 1;
  273.  
  274.                 if((sbuf->info3.EA.vsize) &&
  275.                    (pEAval->size == tEAval->size) &&
  276.                    (pEAval->type == EAT_ASCII) &&
  277.                    (! memicmp(pEAval->data, tEAval->data, tEAval->size))) 
  278.                     showfile(pfname);   // EA matches, display filename
  279.             }
  280.             else showfile(pfname);      // no EA entered, display filename
  281.  
  282.         } while(DosFindNext(shandle, sbuf, SCHBUF_SIZE, &scount) == 0);
  283.     }
  284.  
  285.     DosFindClose(shandle);              // close search handle 
  286. }
  287.  
  288. /*
  289.     SHOWFILE: called with filename, displays fully qualified pathname.
  290. */
  291. void showfile(char far *pfname)
  292. {
  293.     char pathname[MAXPATHNAME];         // receives full pathname
  294.  
  295.     count++;                            // count matched files 
  296.                                         // qualify the filename
  297.     DosQPathInfo(pfname, 5, pathname, sizeof(pathname), 0L);
  298.     printf("%s\n", strlwr(pathname));   // and display it
  299. }
  300. 
  301.